פרקי מבוא במדעי המחשב אורי אברהם המחלקה למתמטיקה ומדעי המחשב אוניברסיטת בן גוריון. תשס"ב מהדורה 4
?? =? = = = E??? =? = = = = = H E?? H.*".>#&/+ 8!# 8 #5(+#59 8 :.;5&(<507#5"!"#$%'&(#)*(+#$,-#$./102#3"4.*#567( &(+#)*A"6(,)0 8 /FG<# 8 6-."-)(@"67-.>#05/,.*A.!B<C+#5!53#.>#$( 8 :"#$%A&(#)D.*#(,;> #$%#( 3#/1 3,7 @#$B3;*# 8 #597("LNM5(#5)>AM7"*#0 3#9 8 #5#59?KJ "!3# %A36I"#$ Java &(+#)*WV/1S"6 23#GXP 8 #5#59 "#$O&(#)QP7/,(1.*AM!+&*R13Q#5": +5S.>"!5TAGU.>#5)* M507![,)*6.* U &0506#07" <Y@.6BZB1#([ 79\0]M*^[GB3;7# M5(^P_#$B1# M507#5QM7"*#06;)Z"#$% 3"! 8 #,0[,"f1T M#5`M*Wa,"RM7"*#0[!507 cbd3"!07#[m5p\/1(`m7"*#0]63e#5" 3h(+)*^[.*"iP6!30[V,7"fVj" M7!7"!.>hM50%L@,7 8 9\(+"! 8.50!1T5/#^#55D#56.5gZ/./1(<1 ;(<BZ.!B1!k.>#05/,.#lZZ/3k.*#05/,.mM5g/n.>"o*#/1(,07#].*!7#&>o.>#05/,.p.6B1 Java ^B1* 8 t()>cgd.*#3"*mm*9 8 /# +"q#05.>#5"r)5&!3.sm7!t,t 607#5r.>#05/,.qWM79*#5 +"A#05.>#5"O)5&! "#5OM*96M.5( #59\3"v9*#5?uJ )5;07!&.*#5"!5T6 *"W507" M*9\5T 4#&&>.n3"`M5(#$B7f35T 4#T(1.RM*"# M/,tZ1#@&(#)>!w6#5#)*`507" 507"# +!Z0["#5kM* xm507*yv5* xm(zm539\(1.*#fm5(+#5w#$b3..>*q&(#)>r#tz 1#5 ( 5#)Q"!/ 7# (BI3"6505 507#(3B3&Q3"#5 #@7#3 105(<]"!505@5.7L3U.>##5 I)!%.*#567(].!5./UG2#562ZZ/3[L7 8.50 "!{M.(P5S533G% b#5a5.7"#%(1z)*o.5( 3:M)Z ˆ i t ^ƒ! ~ % ƒy, ƒ
התוכן 7 פרק א מושגים יסודיים מספר עמודים בפרק: 18 פרק ב לשבת מול המחשב 27 פרק ג הוראות בסיסיות ב- Java 30 פרק ד תכניות פשוטות בפונקציות סטטיות 18 פרק ה סמנטיקה של תכניות פשוטות ומבוא לרקורסיה 15 פרק ו מבוא לעצמים 29 פרק ז תכניות מונחה עצמים, עקרון ההכמסה 22 פרק ח הורשה: מבוא ודוגמאות 10 פרק ט חבילות ומשני הפומביות 22 פרק י עוד על הורשה, כלל קביעת התפריט 26 פרק יא ממשקים 12 פרק יב מחלקות מופשטות 34 פרק יג מבני נתונים וטיפוסי נתונים מופשטים
פרק א מושגים יסודיים מטרת הפרק היא יצירת שפת דיון שבה נשתמש לתאר ולהסביר את הנושאים בהם נעסוק: מהו חישוב ומהי תוכנית מחשב. נסביר כמה מושגים יסודיים שנטפל בהם בהמשך בפרוט רב יותר: נתונים,(data),(types אלגוריתם עיבוד נתונים,(data processing) (algorithm) ועוד. טיפוסים ) נתאר מודל פשוט של מחשב ונסביר כיצד הוראות מרכיבות תוכניות מחשב. נסביר את המושגים סמנטיקה וסינטקס. מחשבים יכולים לאסוף, לשמור, ולעבד מידע ונתונים במהירות ובאמינות. בפרק זה נדון במושגים מידע ועיבוד מידע ובמושגים יסודיים קרובים. תהליך עיבוד הנתונים נתון: פיסת מידע המתארת עצם או מצב. נתונים: אוסף של פיסות מידע המתקבל ממספר רב של עצמים או מצבים. למשל, משקלו וגילו של אדם מסוים זהו נתון, ואוסף כל הנתונים הללו באוכלוסייה מסוימת נותן תמונה כוללת על מצב האוכלוסייה. עיבוד נתונים הוא תהליך חישוב המתבצע תוך שימוש בנתונים שתוצאתו היא מידע המעניין את המשתמש. למשל, אם הנתונים הם פירוט גיל ומשקל של אוכלוסיית ישראל, עיבוד נתונים פשוט הוא חישוב המשקל הממוצע בכל גיל וגיל. יש אופנים שונים להצגת נתונים. לתיאור מספר ילדים במשפחה ניתן להשתמש במספרים הטבעיים (הם המספרים,0,1,2). לתיאור מספר קומה בבניין רב קומתי שיכולה להיות מעל או מתחת לקרקע ניתן להשתמש במספרים השלמים (הם המספרים,2-,2+,1-,1+,0), ואם נרצה לתאר מרחק בין שני מקומות נוכל להשתמש במספרים הממשיים (הם המספרים המתאימים לנקודות על הישר). לא רק מספרים לסוגיהם יכולים לשמש כנתונים כי אם גם אותיות ומילים, או צירוף של מילים ומספרים. למשל נתון יכול להיות כתובתו של אדם הכוללת את שם הרחוב, מספר הבית, העיר, המיקוד וכו' ורשימת כתובות כאלה יהוו את הנתונים. נעיר למי שתמה על כך שכללנו את אפס עם המספרים הטבעיים שישנן שתי גישות מקובלות: זו שרואה באפס את הטבעי הראשון וזו שרואה באחד את הטבעי הראשון, הראשונה. ואנו בחרנו בגישה 1 פרק א
טיפוס הוא סוג הנתונים כלומר הקבוצה אליה משתייכים הנתונים (ממשי, טבעי, שלם וכו'). למשל קבוצת כל המספרים השלמים מהווה את טיפוס המספרים השלמים. אם נסמן טיפוס זה באות Z אז ניתן לומר ש 5 שייך ל- Z או "5 הוא מטיפוס Z. אך 0.5 כמובן אינו מטיפוס Z" קלט ופלט בתהליך עיבוד הנתונים אנו מבחינים בין קלט (input) לבין פלט.(output) הקלט הוא חומר הגלם של העיבוד ואילו הפלט הוא תוצאת החישוב. למשל בחישוב מספר ילדים ממוצע למשפחה בישראל, הקלט יהיה טבלת מספרי ילדים במדגם של משפחות והפלט יהיה מספר הילדים הממוצע למשפחה. הקלט והפלט הם נתונים, אך חשוב לציין שהם אינם בהכרח מאותו טיפוס. כפי שראינו, מספר ילדים במשפחה הוא בהכרח מטיפוס השלמים ואילו המספר הממוצע יהיה מן הסתם מטיפוס הממשיים. כמו כן הפלט אינו בהכרח נתון בודד. עיבוד נתונים יכול להפיק סידרת תוצאות של חישובים שונים. אלגוריתם אלגוריתם הוא תיאור מדוקדק של הפעולות שיש לבצע בעיבוד הנתונים להשגת התוצאה הרצויה. למשל אם נתאר את הפעולות שיש לבצע, צעד אחר צעד, לחישוב ממוצע של סדרת מספרים ממשיים הרי שכתבנו אלגוריתם. נעשה זאת: נניח שלפנינו סידרה של k מספרים ממשיים a. 3 a k מספרים אלה מהווים את הקלט. a 1, a 2, אלגוריתם לחישוב ממוצע של מספרים ממשיים יהיה: 1. חבר את כל אברי הקלט. S = a 1 + a 2 + a 3.+a k 2. חלק את הסכום S במספר המחוברים k, ותהי S/k = x התוצאה..3 פלט:.x לעיתים מסבירים את מושג האלגוריתם בעזרת השוואתו למתכון הוראות הכנת תבשיל. (קח כוס עלי ריחן טריים...) מושג האלגוריתם שונה כמובן ממושג המתכון. הוא אינו עוסק בחמרים מתכלים אלא בנתונים מופשטים, והוראותיו הן חד-משמעיות. אולם ההשוואה עוזרת להבין שאלגוריתם הוא מכלול ההוראות ולא בצוע כזה או אחר שלהן. דוגמה הידועה לנו היטב מבית הספר היא אלגוריתם "חילוק עם שארית". ברור שאלגוריתם החילוק אינו פעולת חילוק מסויימת 2 פרק א
המתבצעת על זוג מספרים נתון, שהרי תוצאות החילוק של זוגות מספרים שונים תהיינה שונות, ומשכו של התהליך יהיה שונה. למען בהירות הדיון הבאנו כאן דוגמאות מאד פשוטות אך בדרך כלל אלגוריתם אינו נוסחה שלתוכה מציבים ערכים על מנת לקבל תשובה, אלא תאור תהליך חישוב שלעיתים הוא מורכב ביותר. לכל קלט האלגוריתם יכול לחשב תוצאת פלט מתאימה, והיחס הנוצר בין הקלט לפלט נקרא "הפונקציה שהאלגוריתם מחשב". אם כך האלגוריתם מחשב פונקציה אך הוא איננו פונקציה. כדאי להבהיר נקודה זו היטב ולשם כך נבהיר את מושג הפונקציה. פונקציה פונקציה מוגדרת במתמטיקה כיחס המתאים לכל אבר x בתחומו בן זוג יחיד y הנקרא "ערך הפונקציה ב- ''. x בעוד שאלגוריתם הוא דרך חישוב, הרי שפונקציה היא היחס שבין הקלט לפלט. אפשר שלאותה הפונקציה יותאמו אלגוריתמים שונים המחשבים בדרכים שונות את אותו יחס קלט פלט. ניתן לחשוב על פונקציה כעל טבלה שבה לכל קלט מותאם בשורתו הפלט המתאים. האלגוריתם הוא תמציתי יותר (בדרך כלל) משום שהוא מתאר את שיטת החישוב ולא את רשימת תוצאותיה (שיכולה אף להיות אינסופית). שפת התכנות ותוכניותיה מכונת כביסה מכבסת, מערבל מזון משמש במטבח, אולם המחשב שונה ממכשירים אחרים שאנו מכירים בכך שהוא רב-תכליתי ואופני השימוש בו אינם מוגבלים. ההפעלה של מכשיר כל כך רב תכליתי אינה יכולה להעשות על ידי מתגים וכפתורים בלבד. אנו זקוקים לשפה בה תתוארנה משימות המחשב ושעל פיה יפעל. שפה כזו היא שפת התכנות בעזרתה ניתן לכתוב תוכניות מחשב. שפת תכנות language) (programming היא כלי המאפשר כתיבת אלגוריתמים ותוכניות להפעלת המחשב. תוכנית מחשב היא אוסף מובנה של הוראות הכתובות לפי כללי השפה. לעתים קרובות תכנית היא מימוש של אלגוריתם מסוים, ובכל מקרה ניתן "להריץ" תוכנית, כלומר להפעילה על ידי המחשב. ביצוע ההוראה בתוכנית הוא צעד חישוב קטן ופשוט, וביצוע מכלול ההוראות מסתכם בביצועו של האלגוריתם שיכול לעיתים להיות מורכב ביותר. גם מי שאין לו ניסיון בתכנות בודאי יודע שקיימות שפות תכנות שונות כמו JAVA C,,PASCAL ועוד. לכל שפה יש הגיון וכללים משלה אותם קבעו יוצרי השפה, וכל מי שכותב בשפה מסוימת עליו להישמע לכללי אותה שפה אשר קובעים גם את אוסף הסימנים וגם את המבנה התחבירי של התוכניות הנכתבות. שני מושגים חשובים בהקשר זה הם הפשר (או סמנטיקה) והתחביר (או סינטקס). תחביר (syntax) אלו כללי הדקדוק של שפת תכנות מסוימת אשר קובעים את מבנה התוכניות. 3 פרק א
פשר (semantics) הוא קביעת המשמעות של כל הוראה ותכנית, כלומר קביעת הפעולות שעל המחשב לבצע בקבלת הוראה בודדת ואפילו בקבלת תוכנית שלמה. המושגים תחביר ופשר יכולים להראות בלתי ברורים בקריאה ראשונה אולם האמת היא שאנו נתקלים בהם לעיתים קרובות. לדוגמה, אם ברצונכם לרשום פעולת חיבור של שני המספרים 4 ו- 5, התחביר מחייב לשים את הסימן + בין המספרים, כלומר לרשום 4 + 5 (ולא למשל.(plus(4,5) הפשר לעומת זאת קבע שסימן ה + משמעותו פעולת חיבור בין המספרים ולא פעולה אחרת. הפשר קובע כי חישוב ערכו של ביטוי זה הוא 9 כמובן. כדי שהמחשב יבצע משימה מסוימת עלינו לפרט עבורו את ההוראות המרכיבות את המשימה, כלומר לכתוב תכנית. בהמשך הספר נלמד כיצד לכתוב תוכניות בשפת,Java ובפרקים הבאים נלמד את התחביר ואת הפשר של ההוראות השונות בשפה. אמנם ביצוע התכניות נעשה על ידי המחשב (האלקטרוני) אך הבנת הביצוע והבנת הסמנטיקה של התוכניות היא ברמה המופשטת. ברמה זו אנו מחליפים את החומרה (המחשב על מעגליו האלקטרוניים) במודל של המחשב. נבהיר את המושגים חומרה ומודל בהם השתמשנו. שני מושגים עליהם בודאי שמעתם חשובים לענייננו חומרה ותוכנה. חומרה: החלקים הפיזיים של המחשב. למשל מסך, מקלדת, וכל הרכיבים האלקטרוניים שנמצאים בתוך המארז של המחשב. תוכנה: כל מה שנוגע לתוכניות המחשב בשפות השונות. להפעלת המחשב נזקקים כמובן לשילוב של חומרה ותוכנה, אך כדי להבין כיצד מקושרות ההוראות שאנו נותנים התוכנה לחומרה המבצעת אותם, מספיק להכיר את המחשב ברמה המופשטת, שכן פרטי המעגלים האלקטרוניים, חשובים ומעניינים ככל שיהיו, אינם עוזרים להבנת שפת התכנות ופעולתה. לכן אנו נוותר על אותם פרטים ונכיר מודל פשוט יותר של מחשב. מושג המודל עצמו דורש הבהרה. מושג המודל. המודל,model) דגם) המשמש את הבנאים הוא מבנה מוקטן עשוי בדוגמת הבניין הממשי. דגם כזה משמש לתיאור והבנה של בנין עוד לפני בנייתו. גם מפה היא מודל. היא מתארת בקנה מידה מצומצם ביותר את המציאות הגיאוגרפית, וכמובן שאנו מכירים מפות שונות לאותו אזור: מפת רחובות, מפה כלכלית, וכדומה. מודל, אם כן, הוא תאור פשוט של חלק מהמציאות. המודלים שנעסוק בהם יהיו לא רק פשוטים אלא גם מופשטים, כלומר לא מוחשיים. בעזרת המודלים נוכל להסביר את הסמנטיקה של שפת המחשב בה נעסוק וכן לטפל במושגי תכנות שונים. כאשר למודל יש תפקיד של הסבר והתמצאות הוא אינו חייב להיות מדויק והקשר בינו לבין המציאות אותה הוא מתאר אינו אחד לאחד. מותר למודל להיות פשוט ואף לחטוא למורכבות המציאות, אם בכך הוא משיג את מטרותיו. לדוגמה, מודל בו השמש סובבת את כדור 4 פרק א
הארץ בוודאי מתאים יותר לצורך הסבר לילד קטן את תופעות הזריחה והשקיעה ואת עובדת קיום זמנים שונים במקומות שונים בעולם. מודל המחשב המופשט. המחשב המופשט כולל ארבע יחידות: 1. זיכרון (Memory) בו יושבים הנתונים שאנו נותנים למחשב לעיבוד. (CPU Central Processing Unit) יחידת חישוב מרכזית שמאפשרת ביצוע פעולות.2 פשוטות על הנתונים היושבים בזיכרון. 3. יחידת קלט, כמו מקלדת שמאפשרת לכתוב למחשב את ההוראות ולתת לו את הנתונים. 4. יחידת פלט, כמו מסך המאפשר למשתמש לקרוא את הפלט שהמחשב נתן. זיכרון המחשב מורכב מתאים. בכל תא יכול לשבת נתון אחד בלבד. מספר תאים אלה הוא גדול אך סופי, כלומר כמות הנתונים שהמחשב יכול להכיל מוגבלת. כידוע, המחשב האלקטרוני שומר את נתוניו בזכרון בינארי המורכב מיחידות שוות גודל הנקראות bytes (הזיכרון הוא הומוגני = אחיד, כלומר כל היחידות דומות זו לזו). אולם, כפי שהסברנו, המודל שלנו מתאר את המציאות ברמת הפשטה המתאימה לצרכיו. על כן כל תא בזכרון המודל הוא יחידה היכולה לאחסן נתון כל שהוא, מטפוס מסוים, גם אם הנתון גדול מאד. אם כן, במודל שלנו (בניגוד למחשבים האלקטרוניים) הזיכרון אינו הומוגני משום שתאיו מתאימים לטיפוסים שונים ועל כן הם יכולים להיות שונים זה מזה. לכל תא זכרון יש כתובת יחודית, ובעזרת כתובות אלו ניתן לאתר ולגשת אל כל תא בזכרון. יחידת החישוב המרכזית CPU יכולה לגשת אל כל תא בזיכרון, לקרוא את תוכן התא, לבצע פעולת חישוב או עיבוד פשוטה, ולרשום את תוצאת העיבוד בתא כלשהו. נראה דוגמה פשוטה של פעולת המחשב. נניח שאנו רוצים שהמחשב יבצע עבורנו חישוב של פעולת החיבור 5+4. נבקש מהמחשב לבצע את ההוראות הבאות: הקצה שלושה תאים בזיכרון לביצוע המשימה ותן להם את השמות.x, y, z.1 2. שים בתא x את הערך 5. 3. שים בתא y את הערך 4. קח את הערכים מהתאים x ו- y ובצע את הפעולה z = x + y כלומר הכנס לתא z את סכום.4 הערכים שבתאים x ו- y. 5 פרק א
הצג את תוכנו של התא z על המסך. כמובן שהשפה בה השתמשנו כאן לתאור ההוראות היא עברית ולא שפת מחשב אמיתית ופורמלית, אולם במהרה נלמד כיצד לתרגם הוראות מסוג זה לשפת תכנות. von Neumann למודל זה של המחשב שאנו מציגים קראים "ארכיטקטורה של על שמו של מתמטיקאי פורה ורב תחומי (1903 1957) שנמנה עם בוני המחשבים הראשונים. שפה עילית ושפת מכ נה אמנם דברנו על שפות מחשב באופן כולל, אך נהוג להבחין באופן גס בין שני סוגים של שפות מחשב. שפה עילית language) (high level היא שפת מחשב כגון,C,Java ++C שנוח למתכנת לכתוב בהן תכניות ואף לקוראן ולהבינן. המחשב לעומת זאת אינו מבין את השפה העילית באופן בלתי- אמצעי והוא נזקק להוראות הפעלה בסיסיות יותר. המחשב יכול לפעול על-פי הוראות הכתובות בשפת מכ נה language).(machine שפת המכ נה היא למעשה אוסף של אפסים ואחדות (ריבוי של אחת) והיא קשה ביותר להבנה לבני אדם. דוגמה לקטע תכנית בשפת מכ נה יכול להיות: 1101 0000 0000 0111 1011 1111 1110 1000 1101 0010 0000 0111 1011 1111 1110 1000 כמובן שלא נוכל, אלא בקושי רב, להבין מה בדיוק מבצעות שורות אלה. לעומת זאת למחשב ברור לחלוטין מה עליו לעשות בקבלו שורות מסוג זה. מכך משתמע שבכדי להריץ תכנית מחשב עלינו לתרגם בדרך כלשהי את השפה העילית יכול לבצע. Java אותה אנחנו מבינים לשפת מכ נה אותה המחשב (compiler.(compilation תהליך התרגום הזה נקרא הידור (קומפילציה, המהדר (קומפיילר, הוא תכנית מחשב אשר מטרתה היא המרה משפה אחת לשפה אחרת, כלומר מהשפה העילית לשפה ברמה בסיסית יותר. אצל שפת Java ממיר המהדר תכניות הכתובות בשפה העילית לשפה הנקראת Java,Bytecode בשלב נוסף שהוא שלב הפרשנות (אינטרפרטציה, שהיא עדיין אינה שפת המכונה, אלא שפת ביניים. על כן יש צורך.(interpretation (interpreter המפרש (אינטרפרטר, של שפת Java הוא תכנית מחשב בעל תפקיד כפול. הוא מבצע הן תהליך של תרגום והן תהליך של הרצה. במהלך פעולתו לוקח המפרש חלקים קטנים מה- Bytecode, מתרגם אותם לשפת מכונה ומיד מביא להרצתם. 6 פרק א
עוד נשוב ביתר פרוט לפשר ולתחביר של ההוראות המרכיבות את שפת התכנות ולמושגים האחרים שהוזכרו כאן, אך לפני כן כדאי שנלמד לכתוב ולהריץ תוכניות פשוטות, שכן לא נוכל להתקדם בלי ידע וניסיון מעשי. זאת אם כן מטרת הפרק הבא: מבוא מעשי לכתיבה והרצה של תכניות. 7 פרק א
פרק ב לשבת מול המחשב בפרק זה נציג את הצעדים הראשונים הנדרשים כדי לכתוב תכניות בסיסיות ב- Java. נתחיל מכתיבתה של תכנית פשוטה ונסביר את הפשר והתחביר של מספר הוראות בסיסיות ב- Java. נתאר את התוכנות שאנו נדרשים להתקין במחשב בכדי להריץ תכניות ונסביר כיצד הן קשורות לשפה ואיך משתמשים בהן. בהפעילו את המחשב המתכנת נזקק לכלים שמאפשרים לעשות את כל הצעדים הקשורים בכתיבת תכניות, החל מכתיבה ושמירת התכנית בקובץ וכלה בהידורה והרצתה. ישנן סביבות עבודה רבות ושונות אשר מאפשרות לארגן את עבודת המתכנת ביעילות רבה, אולם הפעלתן דורשת לימוד והכנה שעלולים להקשות על המתכנת המתחיל. על כן אנו מאפשרים לתלמיד להשתמש בסביבת עבודה אך ממליצים בפניו על כלים פשוטים יותר שהם כללים ואינם יעודיים לשפת התכנות. Java,(directory),(editor) אנו מניחים שהקורא יודע להשתמש בעורך לשמור קובץ בספרייה למחוק ולהעתיק קבצים, ולרשום פקודות פשוטות למחשב. מכיון שמערכות ההפעלה שונות זו מזו והכלים שהן מציעות מגוונים, לא ננסה לתאר אותם כאן. אך נאמר רק זאת: עדיף לדעתנו בשלבים הראשונים של הלימוד להשתמש באמצעים הפשוטים ביותר שיש כדי ליצור תמונת עולם פשוטה וברורה. כך, לדעתנו, עדיף להשתמש בעורך פשוט ולא בסביבות עבודה המיועדות לשפה מסוימת. אמנם סביבות אלו נוחות למתכנת המקצועי אך הן עלולות להיות מכשול נוסף בדרכו של המתלמד. (Accessories) אם אתם עובדים עם מערכת ההפעלה Windows תוכלו למצוא בתפריט העזרים שנמצא בתפריט התכניות (Programs) מעבד תמלילים פשוט ומתאים והוא ה- Notepad. בכדי לבצע את תהליך ההידור והפרשנות יש צורך להתקין תכניות מתאימות במחשב. חבילת התוכנה המכילה את המהדר, המפרש וסודות נוספים של שפת Java נקראת Java Development Kit או בקיצור.JDK אנו מניחים שתוכנות אלו עומדות לרשותכם. פרק ב 1
תכנית ראשונה בשפת Java נסתכל על תכנית פשוטה בשפת Java שכל מטרתה היא להדפיס את המילים המסך: "Hello World" על הקלידו תכנית זו לעורך כלשונה ושמרוה בקובץ ששמו את התכנית ללא שגיאות. הדרו את התכנית על-ידי הפקודה // Prints Hello World on the screen class Hello { public static void main(string[] args) { System.out.println( Hello World ); // main // class Hello.Hello.java javac Hello.java בדקו היטב שאכן העתקתם בדקו שנוצר קובץ חדש בשם.Hello.class (אם קובץ זה לא נוצר חיזרו ובדקו את הקובץ Hello.java שהקלדתם.) עתה תנו הוראה למחשב לפרש ולהריץ את התכנית על-ידי הפקודה java Hello התוצאה תהיה הדפסת המשפט Hello world על המסך. בתכנית זו מספר יסודות חשובים עליהם נתעכב בקצרה: (comment) השורה הראשונה בתוכנית היא הערה אשר מתחילה ב//- ומסתיימת בסוף השורה. ההערה אינה חלק מהתכנית ואינה משפיעה עליה. אנו מוסיפים הערות בכדי לעזור לקורא האנושי להבין מה התכנית מבצעת. למשל בדוגמה זו אנו מבהירים כי תכנית זו תדפיס את המשפט Hello World על המסך. השורה השניה מתחילה במילה.class תרגום מלה זו לעברית הוא מחלקה. כל תכנית בשפת Hello ממוקמת בתוך מחלקה. על המתכנת לבחור שם עבור המחלקה (אנחנו בחרנו בשם Java רצוי ששם המחלקה יעיד על תוכנ ונהוג להתחילו באות גדולה. בכל אופן שם זה נתון.( לבחירתכם. הגדרת המחלקה נפתחת בפותח מסולסל, {, ומסתיימת בסוגר המסולסל האחרון בתכנית,. לאחר סוגר זה הוספנו את ההערה // class Hello בכדי להדגיש לקורא שסוגר זה סוגר את הגדרת המחלקה. המבנה הכללי של מחלקה הוא אם כך: 2 פרק ב
class <class name> {... בתוך הגדרת המחלקה אנו נתקלים בשורה: זוהי כותרת השיטה הראשית public static void main(string[] args) { (method) שיטה.main היא אוסף של הוראות המלוכדות תחת שם אחד. כמו המחלקה גם השיטה נפתחת בפותח { ונסגרת בסוגר {. בתוך הגדרת השיטה מצויות ההוראות ובמקרה שלנו קיימת רק הוראה אחת. כל תכנית בשפת Java חייבת להכיל את השיטה.main השיטה גם את המילים בוודאי שמתם לב כי כותרת השיטה main היא ארוכה ומכילה בנוסף לשם.public, static, void, (String[] args) בשלב זה לא נתעכב להבין את משמעותן של מילים אלו. הן תתבררנה בהמשך. חשוב בכל אופן לדעת כי חובה לרשום את הגדרת השיטה main בדיוק כפי שהיא נכתבה בדוגמה בכדי לעמוד בכללי התחביר של השפה. המבנה של השיטה הוא אם כך: public static void main(string[] args) {... ההוראה היחידה בתכנית היא: System.out.println( Hello World ); בוודאי כבר הבנתם שהוראה זו גורמת להדפסת המשפט Hello World על המסך. למעשה הוראה זו תדפיס על המסך כל משפט שיימצא בין הגרשיים שבתוך הסוגריים. מבנה ההוראה הוא: ;( <טקסט שברצונכם להדפיס> ) System.out.println הוראת ההדפסה מסתיימת בסימן נקודה-פסיק (הוא הסימן ). סימן זה אינו חלק ; מההוראה. הוא מסמן את סיומה של ההוראה ומפריד אותה מהוראות אחרות. ב- Java כל הוראה מסתיימת בנקודה-פסיק. פרק ב 3
נסו לשנות את העימוד ואת הרווחים בין המילים בתוכנית זו על מנת להווכח שההידור יצלח והתכנית תפעת. לעימוד וצורת ההצגה של תכניות יש חשיבות רבה עבור האדם הקורא, אולם המחשב יוכל לטפל גם בתכנית הכתובה על פני שורה אחת. טעויות הידור תכנית מחשב צריכה לעמוד בכללי התחביר שכותבי השפה הכתיבו. המהדר בנוי כך שידע לזהות את הפקודות הנרשמות בהתאם לכללי התחביר. במידה ושגיתם בכללי התחביר המהדר לא יוכל לבצע תרגום של הקובץ ובעת תהליך ההידור הוא יתריע על שגיאות התחביר. Hello בדוגמה הבאה יצרנו מחלקה בשם.Hello1 מחלקה זו זהה למחלקה אולם כאן שכחנו לרשום סימן נקודה-פסיק ) ; ( בסוף שורת ההדפסה. ניסיון לביצוע הידור יגרור את התגובה הבאה: Hello1.java:5: ; expected. System.out.println("Hello World") ^ 1 error המהדר מודיע למתכנת מפורשות כי בשורה 5 חסר סימן נקודה-פסיק. שימו לב לסימן ^ (המכונה באנגלית (caret המורה על מיקומו של הסימן החסר. על המתכנת לשוב לקובץ,Hello1.java לתקן את השגיאות עליהן התריע המהדר, לשמור את הקובץ מחדש ולשוב ולבצע את תהליך ההידור. יתכן כי גם הניסיון השני ואף השלישי לא יעברו בהצלחה בשל טעויות שלא זוהו על-ידי המהדר בתהליכי הידור קודמים. בכל אופן יש לשוב ולתקן, לשמור ולהדר עד אשר תהליך ההידור יעבור בהצלחה, כלומר המהדר יצליח ליצור את הקובץ.Hello1.class 4 פרק ב
שפת בפרקים הבאים נפתח בהדרגתיות ובפירוט רב את המושגים התכנוניים הכלליים ואת יסודות.Java אולם, על-מנת לתת לקורא מושג ראשוני לקראת מה אנו מובילים, חשבנו לתת כאן דוגמאות של תכניות שלמות. גם אם הן מסובכות בשלב זה של הלימוד, ת תרנה דוגמאות אלו רושם מה וניסיון שיעזרו בתהליך הממושך והמפורט שיבוא בהמשך. לקוראים שגישה זו אינה נוחה, נאמר רק שניתן גם לפסוח על חלק זה משום שכל מה שיאמר בו יוסבר אחר-כך וביתר פירוט. בשלב זה של לימודנו המילה מחלקה (class) מציינת תכנית מחשב ב- Java. שנקרא לה,Example1 קובעת ערך למשתנה x ומדפיסה ערך זה על המסך: המחלקה הבאה, הקלד את התכנית ושמור אותה בקובץ ששמו מתן הפקודה 1 class Example1 { 2 public static void main(string[] args) { 3 int x = 37; 4 System.out.println(x); 5 6 // Example1,Example1.java javac Example1.java ואחר-כך הדר את התכנית על-ידי למערכת. כפי שהסברנו יווצר קובץ בשם וניתן להריצו (להפעיל את התכנית) על-ידי פקודת המערכת Example1.class.java Example1 המספר 37 יודפס על המסך. נסה לשנות מעט את התכנית ובדוק את השפעת השינויים (כלומר, חזור על תהליך ההידור וההרצה). שנה את הרווחים ואת המעבר לשורה חדשה במקומות שונים כדי להיווכח ש- Java אינה מתייחסת לרווחים (כולל הסימן לשורה חדשה והסימן.(Tab מובן שלא ניתן לפרק מילה באמצעיתה. נסה, למשל, לכתוב 3 7 במקום 37. המהדר יודיע על טעות ולא ייצור את קובץ Example1.class חדש. לעומת זאת, כתיבת -37 במקום 37 תביא לשינוי המצופה. בשורה 6, הסוגר המסולסל הימני, הוא חלק מהתכנית, אך המשך השורה, התכנית. // Example1 הוא הערה ואינו חלק של באופן גס ניתן להבחין בתכנית שלנו בין מסגרת לבין תוכן. המסגרת היא די קבועה ואילו התוכן משתנה מתכנית לתכנית. בדוגמה שלנו המסגרת היא: class Example1a { public static void main(string[] args) { תוכן // Example1 פרק ב 5
התוכן הוא מה ש"עושה את העבודה" אך בלי המסגרת לא נוכל לכתוב תכניות. רוב המילים המופיעות במסגרת הן מילים שמורות,(reserved words) כלומר, מילים שמשמעותן קבועה ב- Java ולא ניתן להשתמש בהן אלא למטרות לשמן הן נקבעו. המילה class בשורה הראשונה היא מילה שמורה ופירושה מחלקה. שם המחלקה נקבע על-ידינו וניתן היה לבחור שם אחר (ולשנות את שם הקובץ בהתאם). בשלב זה של הלימוד אנו מציעים לקורא לקבל את המסגרת כמצוות אנשים מלומדה ולהתרכז בתוכן; במהרה תהיה כתיבתה קלה ובהמשך נסביר את המשמעות המלאה ואת ההיגיון של רכיביה השונים. התוכן מוקף בסוגריים מסולסלים וליחידה הכוללת את הסוגריים והתוכן אנו קוראים בלוק. הבלוק בדוגמה שלנו מורכב משתי הוראות: זה הסוגר המסולסל השמאלי הפותח את הבלוק { int x = 37; System.out.println(x); זו ההוראה הראשונה זו ההוראה השניה זה הסוגר המסולסל הימני הנועל את הבלוק ההוראה הראשונה היא מסוג הנקרא הכרזה-אתחול: int x = 37; הוראה זו קובעת שהמשתנה x מקבל ערכים שהם מספרים שלמים כלומר ש x הוא מטפוס הוא קיצור של int) int (integer x וכן שהערך התחילי של x הוא 37. המילה x (מילה המורכבת מאות אחת) נקראת משתנה (variable) משום שערכה יכולה להשתנות במהלך התכנית. בתכנית שלנו הערך של אינו משתנה, אך כבר בדוגמה הבאה נראה את אפשרות השינוי. המתכנת חופשי לבחור את שמות המשתנים. נסה לכתוב שם אחר במקום,x ושנה את x בהתאם הן בשורה 3 והן בשורה 4 כדי להיווכח שאין שינוי בהתנהגות התכנית. חופש זה אינו מוחלט משום שלא כל צירוף אותיות יכול להיבחר כשם של משתנה. למשל, מילים שמורות אינן יכולות לשמש כמשתנים. ההוראה int ;37 = x היא קיצור של שתי הוראות שניתן היה לכותבן בנפרד: ההוראה הראשונה כאן היא הוראת הכרזה: ואילו ההוראה השניה, Java הוא.= int x ; x = 37 ; int x; מכריזה שהטיפוס של המשתנה ; 37 = x היא הוראת השמה שנותנת ל- x את הערך x הוא int 37. סימן ההשמה ב- ההוראה השניה בתכנית היא הוראה להדפיס את ערך המשתנה x על המסך. השתמשנו בהוראת ההדפסה בתכנית הראשונה: System.out.println( Hello world ); 6 פרק ב
נסו להחליף את הוראת ההדפסה בתכנית שלנו בהוראה: System.out.println( The value of the variable is + x); וראו מה קורה כאן. הערך המופיע בין הסוגריים העגולים נקרא פרמטר. ;(פרמטר) System.out.println כלומר, The value of the variable is + x הוא הפרמטר. בתכנית המקורית, המשתנה x עצמו היה הפרמטר. בדוגמאות שניתן בהמשך נרשום רק את הבלוק את התוכן של התכנית ועליכם יהיה לעטוף את הבלוק במסגרת כדי לכתוב מחלקה אותה תוכלו להדר ולהריץ. בדוגמה הבאה נראה כמה אופנים בהם ניתן לשנות את ערכי המשתנים: ההוראה בשורה 2 מכריזה על משתנה x מטיפוס int וקובעת את ערכו 1 { 2 int x = 37; 3 int y; 4 y = x + 5; 5 System.out.println(y); 6 x = x + 1; 7 System.out.println(x); 8 System.out.println(y); 9.37 ההוראה int y בשורה 3 רק מכריזה על y כעל משתנה שתחומו הוא אוסף המספרים השלמים מטיפוס אינה קובעת ערך ל- y ולאחריה אין ל- y ערך. רק בשורה 4 נקבע ל- y הערך ניתן להיווכח כשמדפיסים את.int הוראה זו + 5,x כלומר,.42 בזאת y בשורה 5. השתמשנו כאן בהוראה println(y) שמדפיסה את ולאחריו שורה חדשה, על-מנת שלא להדפיס את הערכים הבאים באותה שורה, כשהם צמודים. ההוראה בשורה 6, y ;1 + x x = היא הוראת השמה (assignment) שנותנת ל- x את ערכו הקודם של x ועוד אחת. כיון שערך x לפני ביצוע ההוראה הוא 37, יהיה ערכו לאחריה 38. הוראה זו מבליטה היטב שהסימן = אינו סימן השוויון, שהרי לא יעלה על הדעת ש- x שווה ל- 1 + x. סימן השוויון ב-,Java כפי שנראה עוד מעט, הוא ==, ואילו = הוא סימן ההשמה. ההדפסה האחרונה של y תיתן שוב את הערך 42. כלומר, y לא השתנה לאחר ש- x ש נה. כל הוראה, ובכלל זה ההשמה y = x + 5 שבשורה 4, מתבצעת רק פעם אחת ואין בה איזו קביעה של שוויון שחייב להתקיים באופן תמידי. הדוגמה הבאה תדפיס את כל המספרים הטבעיים שבין המספר from (שנקבע להיות 1 בדוגמה) למספר to (שנקבע להיות 100): פרק ב 7
1 { 2 int from = 1; 3 int to = 100; 4 int i = from; 5 while (i <= to) { 6 System.out.println(i); 7 i = i + 1; 8 9 System.out.println( Exiting from the loop. The value of i is + i); 10 ההוראה הראשונה היא הוראת הכרזה-אתחול שנותנת למשתנה from את הערך 1. לאחריה נקבע ערך המשתנה to להיות 100 וערך המשתנה,from להיות ערכו של i זו הוראת חזרה שניתן להציגה בעברית במילים הבאות: כל עוד התנאי כלומר, 1. עכשיו באה הוראת i to מתקיים, יש.while להדפיס את i ולהגדילו ב 1 -. שימו לב שסימן היחס ללא רווח בין שני הסימנים < ו-=. לתנאי נכתב ב- Java כך => ויש להקליד סימן זה i => to קוראים "ביטוי בוליאני" משום שהביטוי הוא או אמיתי או שקרי, ולשתי האפשרויות אמת/שקר קוראים "ערכים בוליאניים". ניתן להציג את הבלוק בתרשים זרימה כך: התחלה from = 1 to = 100 i = from i to? true false print(i) i = i + 1 הדפסה סיום 8 פרק ב
מעקב אחר ביצוע התכנית יראה לנו שהלולאה מתבצעת בדיוק 100 פעמים ומדפיסה את המספרים מ 1 - עד 100, ואחר-כך מודפס המספר 101. (מדוע?) הכרזנו עד כה על משתנים מטיפוס,int אך יש ב- Java טיפוסי נתונים נוספים שניתן להכריז על משתנים בהם. למשל, double מייצג את המספרים הממשיים. הבלוק הבא קובע ש- x משתנה ממשי שערכו -35.055 ומחלק אותו ב 2 -: { double x = -35.055; x = x / 2; System.out.println(x); גם כאן אנו ממליצים לקורא לעשות ניסויים קטנים ולבדוק את פעולת הכפל * והחיבור +, וכן לבדוק מה קורה כאשר משלבים בביטוי אחד משתנים מטיפוס double ומטיפוס.int למשל, הוסף לבלוק את השורות: int k = 5; x = x + k; System.out.println(x); מה יקרה כאשר תכתוב k? = x פעולת החילוק / מוגדרת גם על מספרים שלמים מטיפוס int והיא מחזירה מספר שלם. בדוק את הערכים 5/2, -7/3 וכו', ונסה להגיע למסקנה. הפעולה % מוגדרת רק על מספרים שלמים: n % m נותנת את השארית של חילוק n ב- m. לדוגמה, 10 % 3 שווה ל 1 -. היחס == 0 2 m % אומר ש 2 - מחלק את m ללא שארית; כלומר, m מספר זוגי. ובאופן כללי יותר, == 0 m n % אומר ש- m מחלק את n. הנה דוגמה לבלוק שמדפיס את כל המחלקים של 100 החל מ 1 -, כלומר, את כל המספרים ש 100 - מתחלק בהם ללא שארית: { int from = 1; int to = 100; int division = from; int middle = to / 2; while (division <= middle) { if (to % division == 0) System.out.println(division); division = division + 1; פרק ב 9
(לקורא: מדוע לולאת ה while מגבילה את ערך division עד?) middle בואו ונסכם את ההוראות שפגשנו עד עתה: 1. הוראת הכרזה מכריזה על משתנה חדש. צורתה של הוראת הכרזה היא: ;<משתנה> <טיפוס> int x5; למשל : String,boolean double הטיפוס יכול להיות,int או, כפי שנראה עוד מעט, גם ועוד טיפוסים עליהם נלמד בהמשך. המשתנה יכול להיות צירוף כלשהו של אותיות וספרות, ובלבד שהצירוף אינו פותח בספרה. כלומר, 5x אינו יכול לשמש כמשתנה. כמובן שגם מילה שמורה (כגון,while class.( ועוד) אינה יכולה להיות משתנה. ההגדרה המדויקת של צירופי הסימנים שיכולים לשמש כמשתנים תינתן מאוחר יותר. לצירוף כלשהו של סימנים קוראים מילה. למשל, +$5U היא מילה. לצירוף שיכול לשמש כשם של משתנה או מחלקה קוראים מילה מזהה או פשוט מזהה identifier) 2. הוראת השמה נותנת ערך למשתנה. צורתה: ;<ביטוי ערך> = <משתנה> x = (y + x) / 5; למשל : 3. ניתן לצרף הכרזה והשמה בהוראה אחת שתיקרא הכרזה-אתחול וצורתה היא: ;<ביטוי ערך> = <משתנה> <טיפוס> double pi = 3.14; למשל : 4. הוראת תנאי היא הוראה שצורתה: <מה לעשות אם התנאי מתקיים> (<תנאי בוליאני>) if if (x < y) max = y; למשל, ההוראה מתייחסת לשלושה משתנים,,x,y max ונותנת ל- max את הערך של y אם x קטן מ- y. צורה נוספת של הוראת תנאי מאפשרת לומר מה לעשות כאשר התנאי אינו מתקיים. זו הצורה המלאה אשר משתמשת במילה השמורה else בנוסף ל- if. למשל: if (x < y) max = y; else max = x; 5. הוראת החזרה while מאפשרת ביצוע חוזר ונשנה של הוראה או של בלוק שלם כל עוד תנאי החזרה מתקיים. צורתה של הוראה זו היא: <מה לעשות כל עוד התנאי מתקיים> (<תנאי בוליאני>) while תרשים הזרימה שמתאר את דרך ביצוע הוראת החזרה while הוא: 10 פרק ב
ההוראה הקודמת תנאי שקר אמת מה לעשות כל עוד התנאי מתקיים ההוראה הבאה להוראת חזרה קוראים גם לולאה (loop) בשל צורת תרשים הזרימה שלה. שים לב שאם התנאי אינו מתקיים כלל, אזי גוף הלולאה אינו מתבצע אפילו פעם אחת. למשל, נסה את הקטע הבא: { int i = 1; while (1 == 0) System.out.println(i); וראה מה יקרה כאשר תחליף את התנאי השקרי תמיד בתנאי הוא אמיתי תמיד (למשל, == 1 1). על-מנת להפסיק ריצה של תכנית, נסה את הצירוף <ctrl>-c (או שאל מישהו שמתמצא). כאמור, הטיפוס הבוליאני כולל את שני הערכים.true, false נסה את ההוראה: System.out.println(1 > 0); בבנייה של ביטויים בוליאניים ניתן להשתמש גם בק שרים & (קוניונקציה), (דיסיונקציה) ו-! (שלילה). הנה, למשל, ההוראה להדפסת ערך x אם x נמצא בקטע :(0.56,3.01) if (0.56 < x & x < 3.01) System.out.println(x); והנה ההוראה להדפסת x אם הוא חורג מגבולות אלו: if (x <= 0.56 3.01 <= x) System.out.println(x); ניתן היה לכתוב זאת גם על-ידי שלילת הימצאות x בקטע: פרק ב 11
if (!(0.56 < x & x < 3.01)) System.out.println(x); צירוף של סימנים נקרא מחרוזת. בהוראת הדפסה כאשר כתבנו, למשל, ב- Java, מחרוזות נכתבות בין גרשיים. פגשנו כבר במחרוזת world Hello כפרמטר להוראת ההדפסה. משתנים להיות מטיפוס,String הוא טיפוס המחרוזת. למשל, נסה את הבלוק הבא: ניתן להכריז על { String a = Hello ; String b = world ; String c = a + b; System.out.println(c); אנו רואים שפעולת החיבור + שזה נקרא בלשון טכנית. על מחרוזות היא פעולת הצירוף, או השרשור,(concatenation) כפי מערך הנו סדרה סופית של מספרים או של ערכים אחרים מטיפוס נתון. הטיפוס של כל המערכים שאיבריהם מספרים מטיפוס שאיבריהם מטיפוס int מסומן.int[] באופן דומה, double[],double מסמן את המערכים ו-[] String מסמן את המערכים שאבריהם מחרוזות. בכל פעם שאנו כותבים תכנית עם פונקציה,main אנו פוגשים הכרזת מערך בתוך הסוגריים: main(string[] args) args כאן הוא משתנה ולכן ניתן היה לבחור גם שם אחר עבורו. ניתן להכריז על מערך ולאתחל אותו כמו בדוגמאות הבאות: int[] values = {3, 10, -2, 5; double[] temps = {-0.55, 3.0, 4; boolean[] ba = {true, true, false, true; String[] s = { ab, 305, kl_b ; כאשר מערך v אינו ריק ו האינדקס i מתאים, ה צירוף v[i] נותן את הרכיב במקום ה- i. הספירה מתחילה ב- 0. כלומר 0 הוא תמיד האינדקס הראשון ולכן בדוגמאות שלנו מתקיימים השוויונות: values[0] = 3, values[1] = 10,, values[3] = 5, temps[0] = -0.55, 12 פרק ב
נסו נא לכתוב את ההשמות הללו בבלוק ואחר-כך להדפיס ba[0] = true,, ba[3] = true s[0] = ab, System.out.println(values[2]) וכד'. אין חובה לאתחל מערכים בבת אחת ואפשר גם למלא את המערך בערכים במהלך ריצת התכנית. לשם כך צריך תחילה לקבוע את אורך המערך וליצור אותו. למשל: int[] val; val = new int[3]; val[0] = 3; val[1] = 2; val[2] = 1; המילה השמורה new משמשת לייצור מערכים. אם k מציין מספר טבעי אזי ההוראה: קובעת ש- a מערך באורך (כלומר a[i],(0 i< k הוא a = new int[k];, ואז לכל אינדקס i הנמצא בגבולות המערך k משתנה מטיפוס int וניתן לקבוע את ערכו ולהתייחס אליו כאל כל משתנה אחר. באופן דומה ניתן לייצר מערך באורך k של ערכים מטיפוס double או מטיפוס אחר. המחלקה הבאה מייצרת מערך בגודל 3 של מספרים ממשיים אקראיים בתחום (1,0] (הקטע של המספרים מ 0 - ועד 1, כולל את 0 אך לא כולל את 1): import java.util.random; class Example2{ public static void main(string[ ] args){ double[] array = new double[3]; Random rdm = new Random( ); array[0] = rdm.nextdouble( ); array[1] = rdm.nextdouble( ); array[2] = rdm.nextdouble( ); System.out.println(array[0]); System.out.println(array[1]); פרק ב 13
System.out.println(array[2]); הסבר התכנית: השורה הראשונה נקראת שורת יבוא ).( import import java.util.random; משמעותה המלאה תתברר לנו בהמשך. היבוא של חבילות ומחלקות מוכנות מאפשר למתכנת להשתמש בכלים מוכנים רבי עוצמה; במקרה זה במחלקה. Random השורה הראשונה בגוף התוכנית מכריזה ש- array הוא מערך של מספרים מטיפוס,double ואף קובעת אותו כמערך באורך 3. אם ננסה להדפיס בשלב זה את ערכי איברי המערך נגלה שכולם 0. ההוראה השניה היא הוראת הכרזה אתחול מסוג שעוד לא פגשנו כמותו. Random הוא טיפוס של עצמים שמחוללים מספרים אקראיים, כלומר, שיכולים לספק מספרים אקראיים (שנקבעים אמנם בתהליך מתמטי ידוע). נשים לב למבנה של הוראה זו, מבנה שהוא טיפוסי בתכנות מונחה עצמים: ; ) ( <מחלקה> = new <משתנה> <מחלקה>,new הטיפוס Random הוא מחלקה, ושם-המחלקה מופיע פעם נוספת, אחרי המילה ולאחריו סוגריים עגולים. מבנה זה דומה למבנה של הכרזת אתחול מערכים, אלא ששם השתמשנו בסוגריים מרובעים. בכל אופן, לאחר ביצוע ההוראה, יש למשתנה rdm ערך וניתן לחשוב על ערך זה כעל קופסא שחורה שניתן להשתמש בה מבלי לפותחה. השימוש ב- rdm נעשה בביטוי rdm.nextdouble( ) שמחזיר (נותן) כל פעם מספר ממשי בקטע (1,0] שערכו אקראי. בדוגמה שלנו אנו מבקשים מ- rdm שלושה מספרים בזה אחר זה ושומרים אותם במשתנים מכן מדפיסים את ערכם. array[2] array[0], array[1], ולאחר- אם נרצה לשנות מעט את התכנית הקודמת ובמקום מערך באורך 3 נבקש ליצור ולמלא מערך באורך 10 (למשל), נמצא שהדבר מצריך כתיבה רבה ומייגעת. במקום לרשום עשר שורות: array[0] = rdm.nextdouble();... array[9] = rdm.nextdouble(); ניתן להשתמש בלולאת while ולרשום בלוק כזה: 14 פרק ב
{ int i = 0; while (i < 10) { array[i] = rdm.nextdouble(); i = i + 1; בשפת :for כזו באופן יותר תמציתי במבנה הנקרא לולאת while ניתן לכתוב לולאת Java for (int i = 0; i < 10; i = i + 1) array[i] = rdm.nextdouble( ); הבה ונניח שאנו מבקשים ליצור מערך באורך 100 של מספרים אקראיים, ואחר-כך להדפיס רק את אותם המספרים הנופלים בקטע [0.8,0.75]. הדוגמה המלאה נקראת. Example3 { double[] array = new double[100]; Random rdm = new Random(); for (int i = 0; i < 100; i = i + 1) array[i] = rdm.nextdouble(); for (int i = 0; i < 100; i = i + 1) if (0.75 <= array[i] & array[i] <= 0.8) System.out.println(array[i]); אנו מצפים שיהיו בממוצע 5 מספרים כאלו בהרצה, אם אכן rdm מייצר מספרים אקראיים. פונקציות סטטיות: לעיתים, בתכניות ארוכות במיוחד, אנו נזקקים לבצע פעולה מסוימת או לעשות חישוב מסוים מספר רב של פעמים. במקום לשוב ולכתוב את הקוד (שורות התכנות) מספר רב של פעמים, ניתן לכתוב פונקציה שעושה את הפעולה הרצויה ולקרוא לפונקציה זו בכל פעם,double שרוצים להשתמש בה. בדוגמה הבאה, הפונקציה max "מקבלת" שני מספרים מסוג פרק ב 15
נקרא להם x ו- y, ומחזירה את y אם x < y ומחזירה את x אחרת. התכנית הראשית,,main שלושה מספרים אקראיים ואחר-כך מדפיסה את הגדול מביניהם. הדוגמה המלאה נראית כך: יוצרת import java.util.random; class Example4 { static double max(double x, double y) { if (x < y) return y; else return x; public static void main(string[] args) { double[] array = new double[3]; Random rdm = new Random( ); array[0] = rdm.nextdouble( ); array[1] = rdm.nextdouble( ); array[2] = rdm.nextdouble( ); System.out.print( max( array[0], max(array[1], array[2]) ) ); קלט מהמשתמש: לעיתים קרובות אנו מבקשים לכתוב תכניות שמבקשות מספרים מהמשתמש ופעולת התכנית תלויה בקלט מספרי זה. שפת התכנות Java אינה מציעה אפשרות נוחה לקלוט מספרים או מילים מהמשתמש. השפה משוכללת מאוד ומציעה מגוון רב של אפשרויות להעברת מידע אך הדבר כרוך בתכנות מתקדם שתגיעו אליו רק בהמשך. בינתיים נכתוב פונקציה שתוכלו להעתיקה ולהשתמש בה בכל עת שתחפצו לקלוט מחרוזת או מספר מהמשתמש. לא נרבה להשתמש בפונקציה זו וכל הדוגמאות שנתן לא יסתמכו עליה, אך בכמה תרגילים ובדוגמאות שתרצו לכתוב לעצמכם תוכלו להשתמש בה במידת הצורך. 16 פרק ב
import java.io; class LineReader { InputStream in = System.in; String readline() throws IOException{ int nextbyte = in.read(); String kelet = ; while (nextbyte!= 13){ kelet = kelet + (char)nextbyte; nextbyte = in.read(); in.skip(1); return kelet; // end method readline. int readint() throws IOException{ return Integer.parseInt(readLine()); public static void main(string[] args) throws IOException { System.out.println( What is your name? ); String name = new LineReader().readLine(); System.out.println( Your name is: + name); System.out.println( Give me an integer ); int kelet = new LineReader().readInt(); System.out.println( Your number is: + kelet); פרק ב 17
לסיכום אני מבקש לעודד את אלו שמצאו שפרק זה מעורפל ומבלבל. מטרת הפרק היא להציג כמה דוגמאות כדי שתוכלו להתרשם מהן ולשחק עמן. המשחק וההתנסות, גם ללא הבנה מלאה, חשובים מאד בתהליך הלימוד. אין ספק שבשלב זה רב הסתום על המחוור, ועל התלמיד להתאזר בסבלנות. בהמשך נשתדל מאד להסביר כל דבר המובא לפניכם. 18 פרק ב
פרק ג הוראות בסיסיות ב- Java ההוראות הן אבני הבניין של תכניות המחשב. בפרק זה נתאר באופן מלא ומפורט יותר את ההוראות בשפת.Java נתחיל בתיאור מדויק של אוסף המזהים, ונעבור על ההוראות השונות אחת לאחת. זהו פרק ארוך למדי ומומלץ להתעכב בקריאה הראשונה על ההוראות היותר שימושיות, ומדי פעם לשוב אליו להבהרה ועיון. Java ההוראות של שפת תכנות הן אבני הבניין שמרכיבות את תכנית המחשב. בספרים באנגלית על משתמשים במונח להשתמש במילה הוראה statement.(instruction) שתרגומו הוא "הצהרה" או "טענה", אך אנו מעדיפים כבר פגשנו בהוראות בפרק הקודם, וראינו כיצד משתנים יכולים להופיע בהוראות. למשל, המשתנה x5b מופיע בהוראת השמה: x5b = 17; לא כל צירוף סימנים יכול לשמש כמשתנה. למשל, אסור ששם משתנה יתחיל בספרה, ולכן אינו יכול להיות משתנה. נגדיר להלן אוסף של שמות שייקראו 5xb "מזהים",(identifiers) ונדרוש שכל שם שמופיע בתכנית ב- Java יהיה מתוך אוסף זה. המזהים משמשים באופן כללי כשמות, לא רק של משתנים אלא גם של קבועים, פונקציות ועוד. תחילה נגדיר את אוסף הסימנים שיכולים להופיע במזהים ואחר כך נבהיר אילו צירופי סימנים הם מותרים ומהווים מזהים. הסימנים היכולים להופיע במזהים הם: אותיות לטיניות קטנות :(lower case).1 a, b,, z אותיות לטיניות גדולות :(upper case).2 A, B,, Z 3. ספרות: 0, 1,, 9 4. שני הסימנים $ (דולר) ו-_ (קו תחתון). ניתן היה לבחור במערכת סימנים עשירה יותר או עשירה פחות, ויש מידה של שרירותיות בבחירה זו של מתכנני שפת.Java אך בחירה כלשהי של מערכת סימנים חייבת להיעשות. הגדרה: מזהה הנו סדרה סופית של סימנים מתוך הרשימה המפורטת ב 1-4 - שאינה מתחילה בספרה. 1 פרק ג
x5b למשל, הסדרה היא מזהה,, ומזהה זה שונה מהמזהה X5B משום שיש הבחנה בין אותיות קטנות לגדולות. הסדרה 5XB אינה מזהה כי היא מתחילה בספרה. לאמיתו של דבר, לא כל מזהה יכול להיות משתנה. יש קבוצה של מילים הנקראות מילים שמורות שיש להן תפקיד מוגדר מראש ב- Java, (reserved words) ואיננו חופשיים להשתמש בהן כמשתנים. דוגמאות למילים שמורות: abstract, boolean, char, class, do, else, extends, for, if, implements. כאמור, כל סדרת סימנים מתוך פרטים 1-4 שאינה מתחילה בספרה מהווה מילת מזהה. אך יש גם כללים של סגנון ומוסכמות שנועדו לאפשר למתכנת לקרוא ולהבין בקלות רבה יותר תכניות. לא יעלה על הדעת, לדוגמה, לבחור משתנה בשם _ (קו תחתון) אם כי מבחינת שפת Java הדבר אפשרי בהחלט. עליכם לבחור את שמות המשתנים בשום שכל: לעיתים שם המשתנה מרמז על תפקידו ובחירה מוצלחת מסבירה את התכנית. עצה נבונה היא לבחור "שמות משמעותיים", וכיון שאנגלית היא השפה השלטת בתכנות, שמות אלו יהיו לרוב באנגלית. אין להיבהל משמות ארוכים, אך יש להקפיד על כתיב נכון טעות כתיב מותירה רושם לא-מקצועי, בדיוק כמו עימוד מרושל של תכנית. הכרזת משתנה כל משתנה שמופיע בתכנית חייב להיות מוכרז לפני השימוש הראשון בו. ההכרזה מודיעה על קיום המשתנה ועל טיפוסו. מדוע חייב המחשב להכיר את טיפוס המשתנה? כדי לדעת כיצד לבצע את הפעולות על אותו משתנה. למשל, נניח שעל המחשב לבצע פעולת חילוק: אם x / y = 5 x, y = 2 הם מטיפוס מספר ממשי אז התוצאה היא 2.5 כמובן, אך אם,x y הם מטיפוס מספר שלם, אז תוצאת החילוק היא 2. לכן, על המחשב להכיר את טיפוסי x ו- y כדי לחשב את הביטוי x. / y שתי השורות הבאות מכריזות על x ועל y כעל משתנים מטיפוס :int int x; int y; ניתן לאחד את שתי ההכרזות הללו. השורה הבאה מכריזה בבת-אחת על x ועל y כעל משתנים מטיפוס :int int x, y; ואילו השורה הבאה מכריזה על x ועל y כעל משתנים מטיפוס ממשי :(double) double x, y; באופן כללי, הוראת הכרזה של משתנה בודד היא מהצורה: ;<שם משתנה> <טיפוס> 2 פרק ג
.3.2.1 כלומר, בהוראת הכרזה שלושה חלקים (משמאל לימין): הטיפוס, שם המשתנה עצמו, סימן הפיסוק ; (נקודה-ופסיק,.(semicolon אפשר להכריז בבת-אחת על הטיפוס (המשותף) של כמה משתנים. המשתנים הללו מופיעים ברשימה כאשר סימן פסיק מפריד בין משתנה למשתנה. משתנים היא: כלומר, הצורה הכללית של הכרזה ;<רשימת משתנים> <טיפוס> כאשר רשימת משתנים יכולה להיות משתנה בודד או סדרת משתנים (שונים זה מזה כמובן) אשר סימן הפסיק מפריד בין כל שני משתנים עוקבים. כיצד נוכל לתת הגדרה פורמלית למושג זה "סדרת משתנים"? עבור משתנה בודד ההגדרה תהיה: <שם משתנה> ועבור שני משתנים מופרדים בפסיק: <שם משתנה>,<שם משתנה> עבור שלשה: <שם משתנה>,<שם משתנה>,<שם משתנה> וכך הלאה. על מנת להגדיר בבת-אחת את המושג "רשימת משתנים" נעזר במערכת ההגדרות הבאה: <רשימת משתנים>, <שם משתנה> <שם משתנה> =: <רשימת משתנים> הסימן =: משמש כסימן ההגדרה. הביטוי שמימין לסימן =: מגדיר את המושג הנמצא משמאלו, כלומר את המושג <רשימת משתנים>. הסימן משמעו "או". כלומר, ההגדרה כולה אומרת: רשימת משתנים היא משתנה יחיד או מורכבת ממשתנה שלאחריו סימן פסיק ולאחריו רשימת משתנים. כלומר, אנו מגדירים את המושג <רשימת משתנים> בעזרת מושג זה עצמו. האם אין כאן פגם של הגדרה מעגלית? ובכן, הגדרה זו שייכת לסוג הגדרות שנקרא "רקורסיבי". ההגדרה בונה את אוסף כל רשימת המשתנים החל מהרשימה הפשוטה ביותר (המכילה משתנה בודד) ונותנת את הכלל שמאפשר יצירת רשימה ארוכה יותר: אם L היא רשימת משתנים שכבר נבנתה, ואם X הוא משתנה כלשהו, אז,X L היא רשימת משתנים. כדי למנוע ספק, נעיר שהסימן =: והסימן המופיעים בהגדרה זו אינם סימנים של שפת סימנים שבעזרתם אנו יכולים לתאר את השפה. Java אלא עוד נעיר שההגדרה הפורמלית שנתנו עבור המושג "רשימת משתנים" אינה כוללת בחובה את הדרישה שהמשתנים ברשימה שונים זה מזה, ואנו חייבים לומר זאת בנוסף. 3 פרק ג
הוראות השמה (assignment statements) הוראת השמה ב- Java היא תמיד מהצורה: ;<ביטוי> = <משתנה>,(expression או term) הסימן = הוא סימן ההשמה. לשמאלו תמיד יופיע משתנה ומימינו ביטוי כאשר סימן הפיסוק ; מסיים את ההוראה. למשל: x2 = y + 5; היא הוראת השמה. ביצוע הוראה זו נעשה על-ידי מציאת ערך (נניח, מטיפוס,(int y לערך זה וקביעת ערך המשתנה הוספת 5 y x2 לתוצאת החישוב. ערכו של אינו משתנה לאחר ביצוע ההוראה. באופן כללי, הביטוי שמימין לסימן ההשמה חייב להיות מטיפוס המשתנה שמשמאל לסימן. (כלל x int T זה של תאימות הטיפוסים יוגמש בעתיד.) למשל, אם הוא ביטוי חשבוני מטיפוס ואם משתנה מטיפוס,int אזי: x = T; היא הוראת השמה. ביצוע הוראת ההשמה נעשה כך. נסתכל במצב לפני ביצוע ההוראה, ונחשב במצב זה את ערכו של הביטוי T. החישוב יעשה כך: לכל משתנה המופיע ב- T יש ערך מספרי וכדי למוצאו, נמצא את כתובת המשתנה בזיכרון ואת ערך תא הזיכרון בכתובת זו. עתה נחשב את ערך הביטוי החשבוני T על סמך ערכי המשתנים. לבסוף נקבע את ערך תא הזיכרון של x להיות תוצאת החישוב. אנו רואים שביצוע הוראת ההשמה הוא תהליך מורכב למדי. תוצאתו אינה משנה כתובת זיכרון של אף משתנה, אך יכולה לשנות את ערך המשתנה שלשמאל סימן ההשמה. הוראת השמה כדוגמת: x = x + 1; בוודאי מוזרה מאוד למי שרגיל לקרוא את = כסימן השוויון: כיצד זה x שווה לעוקבו? אך כמובן שמדובר כאן בסימן ההשמה ולא בסימן השוויון. לבצוע השמה זו, נמצא את ערכו של אחד לערך זה ואת התוצאה ניתן בתאו של לעוקב של ערכו מלפני ביצוע ההוראה.,x.x נוסיף לאחר ביצוע הוראת השמה זו שווה ערכו של x ביטויים חשבוניים לכאורה הוראות השמה הן פשוטות ביותר, אך למעשה הן מחזיקות בחובן את הסיבוך של השפה כולה. זאת מכיון שהביטויים שמימין לסימן ההשמה יכולים להיות מורכבים ומסובכים מאוד. בשלב זה נצטמצם לביטויים פשוטים מטיפוס :int הפעולה החשבוניים (חיבור, כפל, חילוק וכד'). למשל: f3 = (52 * y + first_m) / 2; ביטויים שבנויים ממשתנים, קבועים וסימני 4 פרק ג
היא הוראת השמה, כאשר הביטוי החשבוני מימין לסימן ההשמה מורכב מהמשתנים y ו- first_m, הקבועים 52 ו 2 - וכן סימני הפעולה הבאים: * כפל, + חיבור, / חילוק. כמו-כן משמשים בביטוי סוגריים שקובעים את סדר פעולות החישוב. התחום של המספרים מטיפוס int ב- Java הוא כל המספרים הטבעיים בקטע: [-2147483648, 2147483647] כל מספר בתחום זה נקרא "קבוע". למשל הצרוף 345 נקרא "קבוע". (באנגלית של Java קבועים אלו נקראים (.literals int סימני הפעולה (אופרטורים) שיכולים להופיע בביטויים חשבוניים מטיפוס הם הסימנים הבאים: סימן החיבור +. אם α ו- β הם ביטויים חשבוניים, אז גם α + β הוא ביטוי חשבוני. (בהגדרה זו המונח "ביטוי חשבוני" מתייחס לביטוי מטיפוס (.int.1 2. סימן החיסור -. אם α ו- β הם ביטויים חשבוניים, אז גם α - β הוא ביטוי חשבוני. גם α- הוא ביטוי חשבוני. כלומר, סימן החיסור משמש גם כסימן פעולה דו-מקומי (למשל, בביטוי α) - β וגם כסימן פעולה חד-מקומי (למשל, בביטוי α-). סימן הכפל *. אם α ו- β הם ביטויים חשבוניים, אז גם α * β הוא ביטוי חשבוני. סימן החילוק /. אם α ו- β הם ביטויים חשבוניים, כך גם.α / β פעולת החילוק על מספרים מטיפוס int דורשת בירור, שהרי תוצאת החילוק הרגיל היא בדרך-כלל שבר ולא מספר שלם..3.4 ובכן, החילוק של שני מספרים שלמים מוגדר (במסגרת פעולות על מספרים שלמים) השלם המתקבל כעיגול תוצאת החילוק כלפי 0. כך, לדוגמה, 7/2 אינו 3.5 אלא 3, ואילו כערך. - / 2 (-7) אינו - 3.5 אלא 3 5. סימן פעולת השארית %. אם a ו- b הם מספרים שלמים, אז a % b היא השארית של תוצאת החילוק. למשל, 10%3 שווה 1, ואילו %3( 10-) שווה -. 1 השארית נקבעת על-ידי שני הכללים הבאים (הסבר מלא ינתן בפרק ד' בסעיף הדן באלגוריתם של אוקלידס): א. הערך (a / b) b + a % b שווה תמיד לערך של.a ב. b. כלומר, הערך המוחלט של השארית קטן מהערך המוחלט של a, % b < b =,13/3 ואכן 4 3 + 1 = למשל, = 1 13%3 כי 4 13. דוגמה נוספת: -1 = 3 13) % (- כי - 4 = 3 / 13) (- וגם -1 + 3 4) (- =.-13 ניתן להשתמש בפעולה a % b כדי לקבוע מתי a מתחלק ב- b (ללא שארית): אם = 0 b a % אזי b גורם של a (כלומר b מחלק של.(a 5 פרק ג
. - 3 + 5 -(3 + סוגריים נחוצים לקביעת סדר הפעולות החשבוניות. (5 למשל, אינו שווה ל: בחישוב ערך ביטוי חשבוני, מבוצעות תחילה הפעולות שבתוך סימן הסוגריים. אם T ביטוי חשבוני אזי גם ( T ) ביטוי חשבוני (עם אותו ערך כמובן), וניתן להשתמש בו לבניית ביטויים מורכבים יותר, כגון: ( T ) * x int לסיכום, ניתן לרשום את ההגדרה של ביטויים חשבוניים פשוטים מטיפוס באופן התמציתי הבא: כל מספר בגבולות int הוא ביטוי חשבוני (שנקרא קבוע,constant או literal שזה המונח הטכני שמשמש בהקשר של שפת.(Java אם x משתנה מטיפוס,int אזי x ביטוי חשבוני. אם α ו- β הם ביטויים חשבוניים, ואם OP סימן פעולה (מתוך +, -, *, /, %) אזי α OP β ביטוי.1.2.3 חשבוני. אם α ביטוי חשבוני, אז גם α- ביטוי חשבוני, וכן α+ ביטוי חשבוני. אם α ביטוי חשבוני, אז גם (α) ביטוי חשבוני..4.5 חמשת הכללים הללו מאפשרים בנייה של כל הביטויים החשבוניים. משתנים מטיפוס.int אזי: -(x * 3) / (y + z) למשל, נניח כי,x,y z הם הוא ביטוי חשבוני. הבנייה שלו יכולה להיעשות כך: המספר 3 הוא ביטוי חשבוני על פי כלל 1. * 3 x הוא ביטוי חשבוני על-פי כללים גם.3,2 לכן, (3 * x) ביטוי חשבוני על-פי כלל 5. על-פי כלל,4 3) * -(x ביטוי חשבוני. גם את הביטוי שלנו בעזרת האופרטור /. (z y) + ביטוי חשבוני (על-פי כללים 5). 3, 2, ולבסוף, כלל 3 נותן גם ביטוי מוזרים כמו: + + - + 5 הם ביטויים חשבוניים. יש להימנע מהם, כמובן, מסיבות.( - סגנוניות, אך שפת Java יכולה לטפל בהם (ערך הביטוי המוזר הנ"ל הוא 5 יש ביטויים חשבוניים רבים מטיפוס int שלא נכללים בהגדרה שנת ו לביטויים ה"פשוטים". כאשר נלמד על פונקציות ב- Java נראה שפונקציה יכולה להחזיר ערך מטיפוס,int ואז ביטוי יכול להכיל פונקציה כזו. שפת Java מגדירה קבועים מטיפוס int שלא נכללו בהגדרה שנת ו. למשל, הקבוע: Integer.MAX_VALUE ערכו 2147483647. (נסו לבדוק זאת בתכנית פשוטה ). 6 פרק ג
כאשר קובעים ערכים לכל המשתנים של ביטוי חשבוני, קובעים בכך גם ערך לביטוי כולו. למשל, אם,x y משתנים מטיפוס int שערכם נקבע, אזי לביטוי (3 + y) x * ערך המתקבל מכפל ערך x בערך y ועוד 3. יש קושי בתיאור הפשטני הזה: הקושי נובע מאפשרות החריגה אל מעבר גבולות הטיפוס.int למשל, אם נקבע את y להיות שווה ל- Integer.MAX_VALUE, מה יהיה ערכו של הביטוי + 3 y? תופעה דומה ניתן לראות אם מחשבים את ערכו של.-Integer.MIN_VALUE התשובה ש- Java נותנת מתבררת כאשר חושבים על קטע המספרים [Integer.MIN_VALUE, Integer.MAX_VALUE] כאילו הוא מסודר במעגל שבו הערך MIN_VALUE הוא העוקב של.MAX_VALUE לשם פשטות, טיפלנו עד עתה רק בביטויים מטיפוס int ועתה נדון בטיפוס double ובביטויים מטיפוס.double טיפוס זה מייצג את המספרים הממשיים ברמת דיוק מוגבלת ובתחום מסוים, כמובן שהרי אוסף המספרים הממשיים הוא אינסופי ואף אינו ניתן להימנות. האפיון המדויק של אוסף המספרים הניתנים לייצוג בטיפוס double הוא טכני ואינו מעניין אותנו בשלב זה. נסתפק בכך ש 64 - ביטים עומדים לרשות טיפוס זה, כלומר יש ממשיים. ההכרזה על משתנה להיות מטיפוס double נעשית כרגיל: 2 64 ערכים שונים של מספרים ;<שם משתנה> double ופעולות החשבון המותרות על המספרים מטיפוס -, *, / אך עתה במשמעות שונה double הן:,+ מאשר במספרים השלמים. פעולת הכפל, למשל, היא פעולת הכפל המוכרת על המספרים הממשיים, אך בכפוף למגבלות הדיוק יש "עיגול" בתוצאה. הקבועים (literals) לייצוג מספרים ממשיים הם המספרים הכתובים באופן הרגיל בשיטה העשרונית, עם נקודה. למשל, 31.54406 הוא קבוע. אוסף הביטויים (הפשוטים) מטיפוס מוגדר בדומה להגדרת הביטויים עבור double,int והוראת ההשמה של ביטוי מטיפוס double למשתנה מטיפוס double מוגדרת כמקודם. אנו נתעניין עתה באפשרות של עירוב משתנים מטיפוס ו- int. כל ערך מטיפוס int נחשב גם ערך מטיפוס,double כלומר ההכלה double ממשיים שלמים משתקפת כאן בהכלה.int double double גם יחד נחשב לביטוי מטיפוס יוצא, אם כן, שביטוי המכיל משתנים וקבועים מטיפוס int ו-.double,double ואילו m מטיפוס,int אזי: לדוגמה, אם x = y + m; היא הוראת השמה תקינה משום שהטיפוס של המשתנה x,x y משתנים שהוכרזו להיות מטיפוס שווה לטיפוס הביטוי כולו, דהיינו.double (הערך של הביטוי תלוי, כמובן, בערכים שנקבעו למשתנים y ו- m על-ידי הוראות קודמות בתכנית.) 7 פרק ג
לעתים אנו יודעים שערכו של משתנה מטיפוס בערך זה בביטוי מטיפוס double.int למשל, ערכו הוא המספר השלם 3 (לדוגמה). ננסה לרשום: נניח כי,m n משתנים מטיפוס הוא ערך שלם ואנו מעוניינים להשתמש int ואילו x מטיפוס double אך m = n + x; אם נעשה כן, נקבל הודעת שגיאה מהמהדר: Incompatible type for =. Explicit cast needed to convert double to int. כלומר, יש אי-התאמה של טיפוסים משני עברי סימן ההשמה =. יש צורך בהמרה (casting) מפורשת כדי להמיר את המשתנה x, שהוא מטיפוס,double לערך מטיפוס.int x פעולת casting נעשית על-ידי רישום טיפוס המטרה בסוגריים. כלומר, אם משתנה שטיפוסו double וערכו מספר שלם, אזי: (int)x הוא ביטוי מטיפוס int שערכו הוא ערך המשתנה x (שהוכרז להיות מטיפוס double כאמור). אם ננסה לכתוב: m = n + (int)x; נצליח. אפשר גם לכתוב: m = (int)(n + x); (n + x) ולקבל את אותה תוצאה, אך כעת החישוב נעשה אחרת. תחילה מחושב הביטוי שהוא מטיפוס,double ואחר-כך נעשית ההמרה. למעשה, פעולת ה- casting מוגדרת על כל מספר מטיפוס שלם. אם x מספר מטיפוס,double אז (int)x הוא ביטוי מטיפוס השלם הגדול ביותר שקטן מ- x, ואם,double. x לאו דווקא על אלו שערכם מספר int שערכו הוא הערך השלם של x. אם x 0 אז הערך השלם של x הוא המספר < 0 x אז הערך השלם הוא הנגדי לדוגמה, הערך השלם של 9.8 הוא 9 והערך השלם של - 9.8 הוא -. 9 (מינוס) של הערך השלם של לסיכום, טיפלנו בהוראות השמה מהצורה כאשר ;<ביטוי חשבוני> = x x משתנה והביטוי החשבוני הוא מטיפוס int או מטיפוס.double להיות מעורב, כלומר להכיל משתנים משני הטיפוסים, ואז הוא ביטוי מטיפוס כיצד casting ממיר ביטוי מטיפוס double לביטוי מטיפוס.int ראינו שהביטוי יכול,double וראינו הוראת הכרזה-אתחול 8 פרק ג
ניתן לשלב הוראת הכרזה עם הוראת השמה. במקום לכתוב: ;<משתנה x> <טיפוס> ;<ערך> = <משתנה x> ניתן לכתוב בקיצור: ;<ערך> = <משתנה x> <טיפוס> לדוגמה: double tension = 220.0; הוראה משולבת כזו נקראת הוראת הכרזה-אתחול. הכרזת קבועים המילה השמורה final משמשת להכריז על קבועים. למשל: מכריזה ש- PI הוא קבוע מטיפוס (constant) final double PI = 3.14; double וערכו 3.14. קבוע להופיע פעם נוספת משמאל לסימן השמה. המבנה של הוראת הכרזה על קבוע היא: ;<ערך> = <שם קבוע> <טיפוס> final אינו ניתן לשינוי ואסור לו מקובל לרשום את שם הקבוע באותיות גדולות. הוראת תנאי הנה דוגמה להוראת תנאי: ביצועה כרוך בבדיקת התנאי if (x < y) x = y - x;.x < y אם התנאי מתקיים אזי ההוראה התנאי אינו מתקיים אזי עוברים לביצוע ההוראה הבאה. לתת-ההוראה אפשר גם לכתוב הוראת תנאי עם שני סעיפים. לדוגמה, ההוראה x = y - x מתבצעת ואם x = y - x נקרא if (x > a) x = x - a; else x = a; "סעיף". מורכבת מהתנאי x > a ושני סעיפים. הסעיף הראשון הוא ההוראה a; x = x - שמתבצעת אם,x > a והסעיף השני הוא ההוראה ;a x = שמתבצעת אם התנאי אינו מתקיים. כל הוראת תנאי מתחילה במילה השמורה סעיף אחד) הוא:.if המבנה הכללי של הוראת תנאי פשוטה (דהיינו, עם <הוראה> (<תנאי>) if והמבנה הכללי של הוראת תנאי עם שני סעיפים הוא: > 2 סעיף < else > 1 סעיף < (<תנאי>) if 9 פרק ג
כאשר <סעיף 1> הוא ההוראה המתבצעת כאשר התנאי בסוגריים מתקיים, ואילו <סעיף 2> הוא ההוראה המתבצעת כאשר התנאי שקרי. נשים לב לסוגריים העגולים המקיפים את התנאי בהוראה: הם חייבים להופיע. ביטויים בוליאניים מה הם התנאים שיכולים להופיע בהוראת תנאי? התנאים נקראים "ביטויים בוליאניים" ).(boolean כמו ביטויים חשבוניים יש להם ערך, אך ערך זה אינו מספר כי אם "ערך אמית ת" (או "פסוקים" (sentences) "ערך אמת" ): אמיתי או שקרי. הביטויים הבוליאניים נקראים גם בלוגיקה, משום שהם מתארים מצב מסוים. התנאים הפשוטים ביותר נקראים "פסוקים אטומיים" או "פסוקים ראשוניים". אלו הם התנאים דוגמת: a < 3 שמתקיים אם ורק אם ערך המשתנה a קטן מ 3 -. דוגמה נוספת לתנאי פשוט מתקבלת בעזרת סימן השוויון ==. a == 3.3 מתקיים אם ורק אם a שווה ל באופן כללי, המבנה של תנאים ראשוניים הבנויים מביטויים חשבוניים הוא: <ביטוי חשבוני < 2 <סימן יחס> <ביטוי חשבוני < 1 כאשר סימני היחס האפשריים הם: == סימן השוויון (למשל,.(x + 3 == y.1 =! סימן האי-שוויון, כלומר, שונות (למשל, / 2 y.(x!=.2 < סימן היחס "קטן מ-" (למשל, < 5 x *.(2.3 => סימן היחס "קטן או שווה" (למשל, <= 5 x *.(2.4 > סימן היחס "גדול מ-" (למשל, > 5 x *.(2.5 =< סימן היחס "גדול או שווה" (למשל, >= 5 x *.(2.6 משתנים בוליאניים: הטיפוס.true, false שני ערכים: ומכיל מוגדר ב- Java boolean ניתן להכריז על משתנים וקבועים להיות מטיפוס בוליאני. משתנים וקבועים בוליאניים הם פסוקים ראשוניים. לדוגמה: boolean x; final boolean T = true; 10 פרק ג